package org.pushforward.iwillsurvive;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.pushforward.iwillsurvive.data.DatabaseManager;
import org.pushforward.iwillsurvive.data.TypeValuePair;
import org.pushforward.iwillsurvive.data.TypeValuePair.PairTypeEnum;
import org.pushforward.iwillsurvive.helpers.PageBuilder;
import org.pushforward.iwillsurvive.helpers.Utils;

/**
 * Servlet implementation class Login
 */
@WebServlet("/Login")
public class Login extends HttpServlet 
{
	private static final long serialVersionUID = 1L;
	DatabaseManager db = DatabaseManager.getInstance();
	
    /**
     * @see HttpServlet#HttpServlet()
     */
    public Login() 
    {
        super();
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	@Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
	{
		String email = request.getParameter("email");
		String password = request.getParameter("password");
		
		if (authenticate(email, password, request.getSession()))
		{
			Utils.Log("User found.");
			response.sendRedirect(DatabaseManager.appbase + "/main/index.html");
		}
		else
		{
			Utils.Log("User not found.");
			response.sendRedirect(DatabaseManager.appbase + "/401");
		}
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
	{
		String email = request.getParameter("email");
		String password = request.getParameter("password");
		
		boolean success = addUser(email, password);
		
		PageBuilder refreshPage = new PageBuilder(response);
		String redirect = "<meta http-equiv=\"refresh\" content=\"5; URL=" + DatabaseManager.appbase + "/index.html\">";
		
		if (success)
		{
			refreshPage.AddTitle("User Added")
				.AddHeaderTag(redirect)
				.CloseHead()
				.AddBodyElement("p", "User added to database, you will be automatically redirected back...")
				.CloseBody()
				.PrepareResponse(200);
		}
		else
		{
			refreshPage.AddTitle("User Exists")
				.AddHeaderTag(redirect)
				.CloseHead()
				.AddBodyElement("p", "User already exists, have you forgotten you registered?")
				.CloseBody()
				.PrepareResponse(200);
		}
	}

	/* (non-Javadoc)
	 * @see javax.servlet.http.HttpServlet#doDelete(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
	 */
	@Override
	protected void doDelete(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException
	{
		response.sendRedirect(DatabaseManager.appbase + "/400");
	}

	/* (non-Javadoc)
	 * @see javax.servlet.http.HttpServlet#doPut(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
	 */
	@Override
	protected void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
	{
		response.sendRedirect(DatabaseManager.appbase + "/400");
	}

	/**
	 * connects to the database and checks the login credentials against it.
	 * Also sets the public user fields in session
	 * 
	 * @param email the given email of the user
	 * @param password the given password of the user
	 * @return true if details were confirmed and false if not.
	 */
	private boolean authenticate(String email, String password, HttpSession session)
	{
		// basic setup
		boolean success = false;
		StringBuilder resultSet = new StringBuilder();

		// try to pull the relevant line from the database
		String[] statements = {"select * from users where email=?;"};
		TypeValuePair[][] parameters = {{new TypeValuePair(PairTypeEnum.STRING, email)}};
		success = db.ExecuteStatements(statements, parameters, resultSet);
		
		// if the statement executed, pull up the password field and compare
		if (success)
		{
			String[] userRow = resultSet.toString().split(",");
			SetSessionParameters(userRow, session);
			success = password.equals(userRow[1]);
		}

		return success;
	}

	private boolean addUser(String email, String password)
	{
		boolean success = false;
		String[] selectUserStatement = {"select * from users where email=?;"};
		String[] insertUserStatement = {"insert into users values (?, ?, null, null);"};
		String[] insertRoleStatement = {"insert into roles values (?,'user');",
										"delete from users where email=?;"};
		TypeValuePair[][] parameters = {{new TypeValuePair(PairTypeEnum.STRING, email),
										 new TypeValuePair(PairTypeEnum.STRING, password)}};
		
		// see if user exists
		success = db.ExecuteStatements(selectUserStatement, parameters);
		
		// if it doesn't
		if (!success)
		{
			// insert the user
			success = db.ExecuteStatements(insertUserStatement, parameters);

			// if user inserted
			if (success)
			{
				// insert the role
				db.ExecuteStatements(insertRoleStatement, parameters);
				// check if role insertion worked
				success = db.ExecuteStatements(selectUserStatement, parameters);
			}
		}
		else
		{
			success = false;
		}
		
		return success;
	}

	private void SetSessionParameters(String[] userRow, HttpSession session)
	{
		session.setAttribute("user", userRow[0]);
		session.setAttribute("name", userRow[2]);
		session.setAttribute("photosrc", userRow[3]);
	}
	
}
